package sprites;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import logger.Logger;
import xml.Xml;

public class PointSetSprite extends Sprite {

	private	Set<Point>	points = new HashSet<Point>();

	public PointSetSprite(Point pos, Set<Point> selected) {
		super(pos);
		setPoints(selected);
	}

	@Override
	public boolean containsPoint(Point P) {
		return getPoints().contains(P);
	}

	public Set<Point> getPoints() {
		return points;
	}

	public void setPoints(Set<Point> points) {
		this.points = points;
	}

	public void setPos(Point newPos) {
		Point 			oldPos = this.getPos();

		super.setPos(newPos);

		if (oldPos != null && newPos != null && !newPos.equals(oldPos) && this.getPoints()!=null) {
			int 			dx = newPos.x-oldPos.x;
			int 			dy = newPos.y-oldPos.y;
			HashSet<Point>	newSet = new HashSet<Point>();
			Iterator<Point>	itr = this.getPoints().iterator();
			Point			oldP, newP;

			while(itr.hasNext()) {
				oldP = itr.next();
				newP = new Point(oldP.x + dx, oldP.y + dy);
				newSet.add(newP);
			}
			this.setPoints(newSet);
		}
	}

	public void paintPoint(Graphics G, Rectangle R) {
		int				dx, dy;
		Iterator<Point>	itr = this.points.iterator();
		Point			P;
		Color			oldColor = G.getColor();
		Rectangle		Rp;
		G.setColor(this.getColor());

		while(itr.hasNext()) {
			P = itr.next();
			new Point(P.x, P.y-1);
			new Point(P.x, P.y+1);
			new Point(P.x+1, P.y);
			new Point(P.x-1, P.y);
			dx = P.x - getPos().x;
			dy = P.y - getPos().y;
			Rp = new Rectangle(
				R.x + dx*R.width,
				R.y + dy*R.height,
				R.width,
				R.height
			);

			drawStuff(G, P, Rp);
		}

		G.setColor(oldColor);
	}

	@Override
	public String toXml() {
		String S = "";
		String pointsStr = "";
		int	numPoints = this.getPoints().size();
		int i;
		Iterator<Point>	itr = this.getPoints().iterator();
		Point			P;

		i = 0;
		while(itr.hasNext()) {
			P = itr.next();
			pointsStr += Xml.write("Point_" + Integer.toString(i), P);
			i++;
		}

		S = Xml.write(PointSetSprite.class.getSimpleName(),
				Xml.write("Location", this.getPos())
			+	Xml.write("NumPoints", numPoints)
			+	pointsStr
			);
		return S;
	}

	@Override
	public void fromXml(String xml)  {
			String pointSetStr	= Xml.getTag(xml, PointSetSprite.class.getSimpleName());
			String locationStr	= Xml.getTag(pointSetStr, "Location");
			String numPointsStr	= Xml.getTag(pointSetStr, "NumPoints");
			String pointTag, pointStr;

			int	numPoints = Integer.parseInt(numPointsStr);
			int i;
			Point P;

			this.points.clear();
			for(i=0; i<numPoints; i++) {
				pointTag = "Point_" + Integer.toString(i);
				pointStr = Xml.getTag(pointSetStr, pointTag);
				try {
					P = (Point) Xml.readObj(Point.class, pointStr);
				} catch (InstantiationException e) {
					Logger.println("Failed to instantiate Point_" + Integer.toString(i));
					return;
				} catch (IllegalAccessException e) {
					Logger.println("Failed to access Point_" + Integer.toString(i));
					return;
				}
				this.points.add(P);
			}

			try {
				P = (Point) Xml.readObj(Point.class, locationStr);
			} catch (InstantiationException e) {
				Logger.println("Failed to instantiate location");
				return;
			} catch (IllegalAccessException e) {
				Logger.println("Failed to access location");
				return;
			}
			this.setPos(P);

	}

	public void drawStuff(Graphics G, Point P, Rectangle R) {
		Point	north = new Point(P.x, P.y-1);
		Point	south = new Point(P.x, P.y+1);
		Point	east = new Point(P.x+1, P.y);
		Point	west = new Point(P.x-1, P.y);

		G.fill3DRect(R.x, R.y, R.width, R.height, true);
		G.fillRect(R.x, R.y, R.width, R.height);

		if (!containsPoint(north))	{	this.drawNorthEdge(G, R);	}
		if (!containsPoint(south))	{	this.drawSouthEdge(G, R);	}
		if (!containsPoint(east))	{	this.drawEastEdge(G, R);	}
		if (!containsPoint(west))	{	this.drawWestEdge(G, R);	}
	}

}
